/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#if !defined(AFX_SVGINTERFACE_H__AE98E121_D266_4F12_9036_B592D8F5EB02__INCLUDED_)
#define AFX_SVGINTERFACE_H__AE98E121_D266_4F12_9036_B592D8F5EB02__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <pgl/igfx/FileGfxInterface.h>
#include <pgl/markup/MarkupArchive.h>

namespace gfxinterface
{

/*! \brief SVG interface

  \ingroup IGfxGroup

*/
class CSVGInterface : public CFileGfxInterface  
{
protected:
	//! Linear gradient structore
	struct SLinearGradient
	{
		SRGBA m_cStart;
		SRGBA m_cEnd;
		SPointD m_pStart;
		SPointD m_pEnd;
	};
	//! SVG state
	struct SState
	{
		//! types of fills
		static enum EFillType	
		{	
			//! plain color
			SolidFill=0, 
			//! linear gradient
			LinearGradientFill=1
		};
		//! fill type
		EFillType m_eFillType;
		//! font structure
		LOGFONT m_font;
		//! current stroke color
		SRGBA m_cStroke;
		//! current fill color
		SRGBA m_cSolidFill;
		//! current linear gradient fill
		SLinearGradient m_sLinearFill;
		//! current shadow color
		SRGBA m_cShadow;
		//! current linewidth
		double m_dLinewidth;		
		//! current dash style
		CString m_sDash;
	};
public:
	virtual void BeginPaint(HDC hDC);
	virtual void EndPaint();
	virtual void AddComment(LPCTSTR str){};
	virtual void PushClipWorld(double llx, double lly, double urx, double ury);
	virtual void PopClipWorld();
	virtual void PushState(){	m_lStates.push(m_state);};
	virtual void PopState()	{	m_state=m_lStates.top(); m_lStates.pop();};
	virtual void DrawGridHor(double llx, double urx, double lly, double ury,double dy);
	virtual void DrawGridVer(double llx, double urx, double lly, double ury,double dx);
	virtual void SetColor(double r, double g, double b, double a = 1);
	virtual void SetFillColor(double r, double g, double b, double a = 1);
	virtual void SetLinearGradientFill(const SPointD& point1, const SPointD& point2, const SRGBA& col1, const SRGBA& col2); 
	virtual void SetShadowColor(double r, double g, double b, double a = 0.2);
	virtual void SetLineWidth(double width);
	virtual void SetDash(LPCTSTR dash);
	virtual void DrawRect(double llx, double lly, double urx, double ury, DWORD dwRectFlag = 0, SPointD sShadowSize = SPointD(0,0));
	virtual void DrawArrow(double tailx, double taily, double tipx, double tipy, double tailthickness, double  headthickness, double headlength, bool filled =true);
	virtual void DrawArrowAbs(double tailx, double taily, double dtipx, double dtipy, double tailthickness, double  headthickness, double headlength, bool filled =true);
	virtual void DrawLine(double x1, double y1, double x2, double y2);
	virtual void DrawLineStrip(const CVectorF& vX, const CVectorF& vY, DWORD eLineTypeFlag =0 , double dTension=0);
	virtual void DrawStepStrip(const CVectorF& vX, const CVectorF& vY, DWORD eLineTypeFlag =0 );
	virtual void DrawBandStrip(const CVectorF& vX, const CVectorF& vYBottom, const CVectorF& vYTop, DWORD eBandTypeFlag = 0, double dTension=0);
	virtual void DrawMultipleLineStrip(int ns, const CVectorF& vX, const CVectorF& vY, DWORD eLineTypeFlag =0 );
	virtual void DrawStock( double x0, double dx, const CVectorF& vHis, const CVectorF& vLows, const CVectorF& vOpens, const CVectorF& vCloses, const SRGBA& cDownColor, DWORD eStockTypeFlag = 0);
	virtual void DrawErrorBars( const CVectorF& vXs,  const CVectorF& vYs,const CVectorF& vUps, const CVectorF& vDowns, double dWidth, bool bAbsolute = true, bool bVertical = true);
	virtual void DrawCircle(double cx, double cy, double radius, DWORD eLineType = LineTypeClosed) ;
	virtual void DrawPolygon(double cx, double cy,  const CVectorF& vPx, const CVectorF& vPy, DWORD eLineType = LineTypeClosed);
	virtual void DrawCircleStrip(const CVectorF& vCx, const CVectorF& vCy, double radius, DWORD eLineType = LineTypeClosed);
	virtual void DrawPolygonStrip(const CVectorF& vCx, const CVectorF& vCy,  const CVectorF& vPx, const CVectorF& vPy, DWORD eLineType = LineTypeClosed);
	virtual void SetFont(const LOGFONT& logFont);
	virtual void DrawText(double x, double y, LPCTSTR str, ETextAlignment ta = TextAlignmentLeft, double angle = 0);
	virtual void DrawTextStrip(const std::vector<SPointD>& points, const std::vector<std::_tstring>& lStrings, ETextAlignment ta = TextAlignmentCenter, double angle = 0);
	void DrawArc(double cnx, double cny, double rn, double angle, double aperture, double rep, DWORD flags);
	virtual void DrawSurf(const contour::TLattice<float>& tLattice, const CVectorF& vColor, DWORD dwFlag=0);
	virtual void DrawVectorField(const contour::TLattice<float>& tLattice, const CVectorF& vVx, const CVectorF& vVy, float fScale = 1, DWORD dwFlags=0);
	virtual double BBToWorldx(double x) const {	return GetWorldLeft()+(x-(double)GetBBLeft())/(double)(GetBBWidth())*(double)(GetWorldWidth());};
	virtual double BBToWorldy(double y) const {	return GetWorldTop()+(y-(double)GetBBTop())/(double)(GetBBHeight())*(double)(GetWorldHeight());};
	virtual double BBToWorldAbsx(double x) const {	return x/(double)(GetBBWidth())*(double)(GetWorldWidth());};
	virtual double BBToWorldAbsy(double y) const {	return y/(double)(GetBBHeight())*(double)(GetWorldHeight());};
	//! Transform world x coordinate to file coordinate x
	virtual double WorldToBBx(double x) const {	return GetBBLeft()+(x-(double)GetWorldLeft())/(double)(GetWorldWidth())*(double)(GetBBWidth());};
	//! Transform world y coordinate to file coordinate y
	virtual double WorldToBBy(double y) const {	return GetMainBBBottom() + GetMainBBHeight() - ((y-(double)GetWorldBottom())/(double)(GetWorldHeight())*(double)(GetBBHeight()) + GetBBBottom());};
	//! Transform world x coordinate to file coordinate x
	virtual double WorldToBBAbsx(double x) const {	return x/(double)(GetWorldWidth())*(double)(GetBBWidth());};
	//! Transform absolute world y coordinate to file coordinate y
	virtual double WorldToBBAbsy(double y) const {	return y/(double)(GetWorldHeight())*(double)(GetBBHeight());};
	virtual LPCTSTR GetFileExt() const;
	virtual double NormBBoxToBBy(double y) const {	return GetMainBBTop() - m_sCurBBox.screen.top + (1-y) * m_sCurBBox.screen.height;};
	virtual double NormClipBBoxToWorldy(double y) const {	return BBToWorldy( GetMainBBTop()-m_rCurClip.top - (1-y) * m_rCurClip.height);};
	virtual double GetWorldClipBottom() const {	return BBToWorldy(GetMainBBTop()-(m_rCurClip.top+m_rCurClip.height));};
	virtual double GetWorldClipTop() const {	return BBToWorldy(GetMainBBTop()-m_rCurClip.top);};
	virtual double GetBBClipBottom() const {	return m_rCurClip.top+m_rCurClip.height;};
	virtual double GetBBClipTop() const {	return m_rCurClip.top;};
	virtual double GetYDirectionUp() const {	return -1;};
public:
	CSVGInterface();
	virtual ~CSVGInterface();

	void DrawDonnut(double cnx, double cny, double rin, double rout, double angle, double aperture, double rep, DWORD flags);
	//! SVG or SVGZ
	static enum EOutputType
	{
		//! creates SVG files (default)
		OutputSVG=0,
		//! create SVGZ files (zipped SVG)
		OutputSVGZ=1
	};
	void SetOutputType( EOutputType eType)			{	m_eOutputType = eType;};
	EOutputType GetOutputType() const				{	return m_eOutputType;};
	
protected:
	void InitState();

	void AddStrokeColorAttrib(markup::CMarkupArchive& xml, bool bContour);
	void AddFillColorAttrib(markup::CMarkupArchive& xml, bool bFilled);
	void GetColorString( const SRGBA& c, CString& str) 		{	str.Format(_T("#%X%X%X"),(int)floor(c.r*15),(int)floor(c.g*15), (int)floor(c.b*15));};
	//! Write
	virtual void WriteHeader();
private:
	EOutputType m_eOutputType;
	std::stack<SState> m_lStates;
	SState m_state;
	long m_liCurDef;
	markup::CMarkupArchive m_xml;
	markup::CMarkupArchive m_xmlDefs;
};

}
#endif // !defined(AFX_SVGINTERFACE_H__AE98E121_D266_4F12_9036_B592D8F5EB02__INCLUDED_)
